﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using 营救宠物.Properties;

namespace 营救宠物
{
    //行列数结构体
    public struct RowLine 
    {
        public int RowNum;
        public int LineNum;
        public RowLine(int row, int line)
        {
            this.RowNum = row;
            this.LineNum = line;
        }
    };

    /// <summary>
    /// 标记单个建筑块属性
    /// </summary>
    public struct BiuildPos
    {
        public int X, Y, Layer;                     //坐标x,y,图层位置Layer

        public BiuildPos(int X, int Y, int Layer)
        {
            this.X = X;
            this.Y = Y;
            this.Layer = Layer;
        }

        public void set(int X, int Y, int Layer)
        {
            if (this.Equals(null)) this = new BiuildPos(X, Y, Layer);
            else
            {
                this.X = X;
                this.Y = Y;
                this.Layer = Layer;
            }
        }
    };

    //建筑块区域 和 图块属性
    public struct Rect_buildPos
    {
        public Rectangle Rect;
        public BiuildPos buildPos;

        public Rect_buildPos(Rectangle Rect, BiuildPos buildPos)
        {
            this.Rect = Rect;
            this.buildPos = buildPos;
        }
    }


    public partial class Form1 : Form
    {
        public toolFunctions F = new toolFunctions();

        public int width, height, border;                   //tileMap块的宽度
        private int TargetWidth, TargetHeight;              //目标宽度和高度

        //pictureBox界面的绘制相关
        RowLine RL1, RL2, RL3;                              //3个绘制区域的行列数
        Rectangle Rect1, Rect2, RectTip, Rect3;             //记录工具块、tileMap图 的表示区域、 编辑区域块解析提示信息区域、建筑图块区域
        private Graphics g1, g2, gBuild;                    //

        Point toolsPos, mapPos, toolSelect;                 //记录在工具栏中、绘制界面中行列位置、在工具条中的选中位置、在建筑图块区域的选中位置
        Random rnd = new Random();                          //随机数

        int[][] mapData;                                    //编辑界面编辑的数据

        string[] OpendFilesName;                            //打开的关卡文件名称
        int curFilePos;                                     //当前所在文件位置

        private Image bg1, bg2;                             //设置工具栏和编辑区域的背景图像

        private Image[][] Images =                          //图元
        {
            new Image[]{ Resources.block1, Resources.block2, Resources.block3, Resources.block4, Resources.block5, Resources.block6, Resources.block7, Resources.block8, Resources.block9},
            new Image[]{ Resources.star1, Resources.star2, Resources.star3, Resources.star4, Resources.star5},
            new Image[]{ Resources.bubble1, Resources.bubble2, Resources.bubble3, Resources.bubble4, Resources.bubble5, Resources.block11, Resources.block12, Resources.block13, Resources.block14 },
            new Image[]{ Resources.animal1, Resources.animal2, Resources.animal3, Resources.animal4,Resources.animal5},
            new Image[]{ Resources.block41, Resources.block42, Resources.addStep, Resources.subStep, Resources.block45},
            new Image[]{ Resources.cage1, Resources.cage2, Resources.cage3, Resources.cage4, Resources.cage5},
            new Image[]{ Resources.eraser, Resources.birth, Resources.shade1, Resources.block17},
            new Image[]{ Resources.cage6, Resources.cage7, Resources.cage8, Resources.cage9, Resources.cage10}
        };
        int eraserNum, birthNum, shadeNum, wallNum;

        private Cursor[][] mouseIcon;      //鼠标图标数组,从Images创建

        private TextBox[] txtRows;         //行概率控制              
        private TextBox[][] txtTools;      //各工具块的概率控制

        private CheckBox[] checkLines;     //列复选框，标识列选中

        private Point MousePoint;          //记录鼠标的位置在各PicBox中的位置
        //建筑块区域
        private Rectangle[] buildRects;    //建筑块中，所有块对应的图形区域
        private int buildIndex = -1;       //建筑块的索引位置
        private Bitmap[] buildTiles;       //所有建筑图块图像
        private string[][] buildsData;     //建筑层数据存储
        private BiuildPos BuildPos;        //标识当前编辑的建筑块，在编辑区中的位置
        private int maxlayerNum;           //建筑块最大图层数
        private string buildPicMap;        //各建筑块对应的图块映射关系


        Queue<Rect_buildPos> RectsQueue = new Queue<Rect_buildPos>();   //各建筑块所在的坐标区域队列
        //Queue<BiuildPos> PosQueue = new Queue<BiuildPos>();           //记录选中的各建筑块位置
        List<BiuildPos> PosList = new List<BiuildPos>();                //记录选中的各建筑块位置
        private Dictionary<Point, int> timeStep = new Dictionary<Point, int>(); //记录各定时炸弹块的，步数定时
        private Point clickTimeStep = new Point(-1, -1);                //记录点中的定时炸弹块坐标

        //private CheckedListBox;
        int toolBoxPos = 0;                //标识鼠标单击了哪个工具框中，1在pictureBox1中、2在pictureBox2中、3在pictureBox3中

        private Point VisPos;              //编辑界面中可见区域行列数位置

        

        public Form1()
        {
            InitializeComponent();
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            //行列数
            RL1 = new RowLine(Images.Length, 9);
            RL2 = new RowLine(9, 9);
            RL3 = new RowLine(8, 9);

            getTargetSize();                                    //获取目标屏幕尺寸

            //设置宽度、边距
            border = 4;                                                         //设置边距
            //width = (int)(380 - 2 * border) / RL1.LineNum;      //设置方格宽度自适应图片框
            width = 38;
            height = 33;


            Rect1 = new Rectangle(border, border, width * RL1.LineNum, width * RL1.RowNum);             //工具栏绘制区域
            RectTip = new Rectangle(Rect1.X, Rect1.Bottom + 2 * border, width * RL1.LineNum, width * 1);//图块解析区域
            Rect2 = new Rectangle(border, border, width * RL2.LineNum, height * RL2.RowNum);            //编辑区域

            Rect3 = new Rectangle(Rect1.Right + 30, border, width * RL3.LineNum, width * RL3.RowNum);   //建筑图块区


            //在对象图片框中创建Graphics对象用于绘图
            g1 = pictureBox1.CreateGraphics();   //工具界面    
            g2 = pictureBox2.CreateGraphics();   //编辑界面  
            gBuild = pictureBoxbuild.CreateGraphics();  //建筑块属性界面

            initCursors();                       //初始创建所有图标
            initMapData();                       //初始化编辑数据

            //工具栏和编辑区的背景图像
            bg1 = Resources.toolsBg;
            bg2 = Resources.backGround;

            pictureBox1.Image = bg1;
            pictureBox2.Image = bg2;

            //初始化最后一行特殊块的编码值
            eraserNum = (Images.Length-1) * 10 + 1;  
            birthNum = eraserNum + 1;
            shadeNum = eraserNum + 2; 
            wallNum = eraserNum + 3;

            timerDraw.Enabled = true;            //延迟绘制界面

            createInputView();                   //创建概率输入框   


            //添加列选择复选框到界面中
            createCheckBoxLines();

            //其他设置信息，控件信息初始化
            InitSetting();

            //初始化建筑图层相关数据
            initRects();        //初始化所有建筑块的区域范围
            initBuildData();    //初始化建筑图块数据
            initBuildTiles();   //初始化所有建筑图块

            setLayerNum(0);

            //鼠标滑动滚轮，改变对应的文本框数值
            textBoxShrink.MouseWheel += new MouseEventHandler(Shrink_MouseWheel);
            textBoxOffX.MouseWheel += new MouseEventHandler(OffX_MouseWheel);
            textBoxOffY.MouseWheel += new MouseEventHandler(OffY_MouseWheel);
            
            //EditViewPannel.AutoScrollPosition = new Point(100, 100);
            //pictureBox2.AutoScrollOffset = new Point(100, 100);
        }

        private void Shrink_MouseWheel(object sender, MouseEventArgs e)
        {
            float shrink = F.ToFloat(textBoxShrink.Text.Trim(), 1);

            textBoxShrink.Text = (shrink + 0.01 * (e.Delta/120)).ToString("F3"); 
        }

        private void OffX_MouseWheel(object sender, MouseEventArgs e)
        {
            int offX = F.ToInt(textBoxOffX.Text.Trim(), 0);
            textBoxOffX.Text = (offX + e.Delta/120).ToString();
        }
        private void OffY_MouseWheel(object sender, MouseEventArgs e)
        {
            int offY = F.ToInt(textBoxOffY.Text.Trim(), 0);
            textBoxOffY.Text = (offY + e.Delta / 120).ToString();
        }



        private void getTargetSize()
        {
            try
            {
                TargetWidth = Int32.Parse(textBoxTargetWidth.Text.Trim());  //设置目标宽度和高度
                TargetHeight = Int32.Parse(textBoxTargetHeigh.Text.Trim());
            }
            catch (Exception ex)
            {
                TargetWidth = 76;
                TargetHeight = 66;
            }

        }

        //---------------------------------------------------------------------------------------------------
        //概率控制
        //---------------------------------------------------------------------------------------------------
        //创建各控件概率输入框
        private void createInputView()
        {
            txtRows = createRowInput();
            txtTools = createToolsInput();
            initProbility();
        }
        //创建控件，用于各行控件的概率输入
        private TextBox[] createRowInput()
        {
            TextBox[] txtRows = new TextBox[RL1.RowNum-1];      //根据工具栏工具行数创建
            
            for(int i=0; i<txtRows.Length; i++)
            {
                txtRows[i] = new TextBox();

                txtRows[i].Width = 24;
                txtRows[i].Height = 8;
                txtRows[i].Top = Rect1.Top + width * (i + 1) - txtRows[i].Height;
                if (i >= 6) txtRows[i].Top += width;
                txtRows[i].Left = Rect1.Left + Rect1.Width + 2;
                txtRows[i].Visible = false;
                //if (i == 0) txtRows[i].Text = "100";            //第0行的默认概率值设为100

                pictureBox1.Controls.Add(txtRows[i]);

                //添加文本变动事件处理函数
                txtRows[i].TextChanged += new System.EventHandler(this.txtRows_TextChanged);
            }

            return txtRows;
        }
        //创建控件，用于所有有效控件的概率控制
        private TextBox[][] createToolsInput()
        {
            TextBox[][] txtTools = new TextBox[RL1.RowNum - 1][];   //根据工具栏工具行数创建

            for (int i = 0; i < txtTools.Length; i++)
            {
                txtTools[i] = new TextBox[RL1.LineNum];             //根据列数创建
                for (int j = 0; j < txtTools[i].Length; j++)
                {
                    txtTools[i][j] = new TextBox();

                    txtTools[i][j].Width = 24;
                    txtTools[i][j].Height = 8;
                    txtTools[i][j].Top = Rect1.Top + width * (i + 1) - txtTools[i][j].Height;
                    if (i >= 6) txtTools[i][j].Top += width;
                    txtTools[i][j].Left = Rect1.Left + width * j + 1;
                    txtTools[i][j].Visible = false;
                    //if (i == 0 && j < Images[1].Length)             //第0行的默认概率值均分
                    //    txtTools[i][j].Text = ((int)(100 / Images[1].Length)).ToString();  

                    pictureBox1.Controls.Add(txtTools[i][j]);
                }
            }

            return txtTools;
        }

        //设置行概率栏是否可见
        private void setRowInputVisible(bool visible)
        {
            for (int i = 0; i < txtRows.Length; i++)
                txtRows[i].Visible = visible;
        }
        //设置行概率栏是否可见
        private void setToolsInputVisible()
        {
            int num;
            for (int i = 0; i < txtTools.Length; i++)
            {
                try { num = Int32.Parse(txtRows[i].Text.Trim()); }  //获取该行的概率值
                catch (Exception e) { num = 0; };

                //bool visible = CheckSetProbility.Checked && (num > 0 || i == 3 || i == 5);//若选中了设置概率，且概率值大于0、为水果行3、为笼子行5，则该行概率可设置
                bool visible = CheckSetProbility.Checked && num > 0;//若选中了设置概率，且概率值大于0，则该行概率可设置
                for (int j = 0; j < txtTools[i].Length; j++)
                    txtTools[i][j].Visible = (j >= Images[i>=6 ? i+1 : i].Length) ? false : visible;      //块不存在，则不可设置概率
            }

            drawToolsDelay();
            //reDraw();           //重绘界面的显示
        }

        //行概率值变动事件
        private void txtRows_TextChanged(object sender, EventArgs e)
        {
            timerDelayDoing(1);
        }

        //延迟一段时间后，执行动作
        private void timerDelayDoing(int n, int delay)
        {
            timerDelay.Interval = delay;
            timerDelayDoing(n);
        }
        private void timerDelayDoing(int n)
        {
            doingNum = n;
            timerDelay.Enabled = true;
        }
        int doingNum = 0;
        private void timerDelay_Tick(object sender, EventArgs e)
        {
            timerDelay.Enabled = false;
            timerDelay.Interval = 450;

            if (doingNum == 1) setToolsInputVisible();      //设置各输入框是否可见
            else if (doingNum == 2) setBuildAttr(BuildPos.X, BuildPos.Y, BuildPos.Layer);       //显示选中的建筑块
            else if (doingNum == 4) upDataBuild0();         //更新使用的建筑块属性
            else if (doingNum == 5) drawTools();            //更新工具栏的显示
        }

        //获取当前编辑界面中设置的概率值，转化为二维数组数据
        private int[][] getProbility()
        {
            string strNum = "";
            int num;

            int[][] probility = new int[RL1.RowNum - 1][];      //创建概率数组
            for (int i = 0; i < probility.Length; i++)
            {
                probility[i] = new int[RL1.LineNum + 1];        //多创建一个空间，用于存储该行的概率值
                for (int j = 0; j < probility[i].Length; j++)
                {
                    strNum = j == 0 ? txtRows[i].Text : 
                        txtTools[i][j - 1].Text;                //第0列保存工具栏的行概率值

                    try { num = Int32.Parse(strNum.Trim()); }   //转化为数据           
                    catch (Exception e) { num = 0; }

                    if (j > Images[i].Length) num = 0;          //对应的块不存在，概率值清0
                    probility[i][j] = num;                      //存储到数组中
                }
            }
            return probility;
        }

        //将数组的数据，输入到对应的概率编辑框中
        private void setProbility(int[][] probility)
        {
            for (int i = 0; i < txtTools.Length; i++)
            {
                for (int j = 0; j < txtTools[i].Length + 1; j++)
                {
                    if (j == 0) txtRows[i].Text = (i >= probility.Length) ? "0" : probility[i][j].ToString();
                    else txtTools[i][j - 1].Text = (i >= probility.Length || j >= probility[i].Length) ? "0" : probility[i][j].ToString();
                }
            }
            
        }

        //初始化编辑界面中的概率
        private void initProbility()
        {
            //初始化概率数据
            int[][] P = new int[txtTools.Length][];
            for (int i = 0; i < P.Length; i++)
            {
                P[i] = new int[txtTools[i].Length + 1];
                for (int j = 0; j < Images[i].Length + 1; j++)
                {
                    if (i == 0)
                    {
                        if (j == 0) P[i][j] = 100;
                        else P[i][j] = 100 / Images[i].Length;
                    }
                }
            }

            setProbility(P);    //设置到概率编辑界面中
        }

        //---------------------------------------------------------------------------------------------------
        //创建列复选框
        private void createCheckBoxLines()
        {
            checkLines = new CheckBox[RL2.LineNum];
            for (int i = 0; i < checkLines.Length; i++)
            {
                checkLines[i] = new CheckBox();
                checkLines[i].Text = "";
                checkLines[i].SetBounds(Rect2.Left + width * i, Rect2.Top, 13, 13);
                checkLines[i].Visible = false;
                pictureBox2.Controls.Add(checkLines[i]);
            }
        }

        //设置控件的可见性
        private void setCheckLineVisible(bool visible)
        {
            for (int i = 0; i < checkLines.Length; i++)
                checkLines[i].Visible = visible;
        }

        //---------------------------------------------------------------------------------------------------
        //界面绘制
        //---------------------------------------------------------------------------------------------------

        //使用工具栏中的图像创建鼠标显示图标，初始创建所有图标
        private void initCursors()
        {
            mouseIcon = new Cursor[RL1.RowNum][];
            for (int i = 0; i < RL1.RowNum; i++)
            {
                mouseIcon[i] = new Cursor[RL1.LineNum];
                for (int j = 0; j < RL1.LineNum; j++)
                {
                    if(i<Images.Length && j<Images[i].Length)
                        mouseIcon[i][j] = F.GetCursor(Images[i][j], (int)(width * 0.75));
                    else mouseIcon[i][j] = Cursors.Default;

                }
            }
        }

        //初始化界面编辑数据
        private void initMapData()
        {
            if (mapData != null) mapData = null;

            mapData = new int[RL2.RowNum][];
            for (int i = 0; i < mapData.Length; i++)
                mapData[i] = new int[RL2.LineNum];
        }

        //控制界面重新绘制显示内容
        private void reDraw()
        {
            timerDraw.Enabled = true;                       //启动定时，延迟绘制界面
        }
        private void timerDraw_Tick(object sender, EventArgs e)
        {
            timerDraw.Enabled = false;
            timerDraw.Interval = 30;
            draw();
        }

        //界面的绘制
        private void draw()
        {
            drawTools();
            drawMap();
            //setBuildAttr();
        }


        //绘制工具栏
        private void drawToolsDelay()
        {
            timerDrawTool.Enabled = true;
        }
        private void drawTools()
        {
            F.drawQipan(g1, RL1.RowNum, RL1.LineNum, Rect1.X, Rect1.Y, width);
            F.drawQipan(g1, 1, RL1.LineNum, RectTip.X, RectTip.Y, width);

            //F.drawQipan(g1, RL3.RowNum, RL3.LineNum, Rect3.X, Rect3.Y, width);

            //在工具栏中绘制所有工具图元
            for (int i = 0; i < Images.Length; i++)
            {
                for (int j = 0; j < Images[i].Length; j++)
                {
                    eraser1(i, j);                      //擦除坐标处的图像

                    drawPic1(i, j, Images[i][j]);
                    drawNumber1(i, j, (i+1)*10 +(j+1)); //绘制块对应的数值
                }
            }
        }

        //绘制工具栏
        private void drawMap()
        {
            g2.DrawImage(bg2, 0, 0, pictureBox2.Width, pictureBox2.Height);
            F.drawQipan(g2, RL2.RowNum, RL2.LineNum, Rect2.X, Rect2.Y, width, height);

            //绘制从VisPos.X 到 VisPos.X + 10 这11行
            int bottomRow = VisPos.X + 11 -1;                            //可见区域最底行
            if(bottomRow > RL2.RowNum-1) bottomRow = RL2.RowNum-1;       //最大行位置

            for (int i = 0; i < 11 && bottomRow - i>=0; i++)             //显示可见区域的11行
            {
                for (int j = 0; j < RL2.LineNum && j < VisPos.Y + 9; j++)//显示可见区域的9列
                    drawPic2(bottomRow - i, j);                         //重绘界面中的块    
            }

            drawBildings();                                             //重绘建筑图块
        }

        //绘制工具栏
        private void drawMap_0()
        {
            g2.DrawImage(bg2, 0, 0, pictureBox2.Width, pictureBox2.Height); 
            F.drawQipan(g2, RL2.RowNum, RL2.LineNum, Rect2.X, Rect2.Y, width, height);

            for (int i = RL2.RowNum-1; i >= 0; i--)
            {
                for (int j = 0; j < RL2.LineNum; j++)
                    drawPic2(i, j);                     //重绘界面中的块    
            }

            drawBildings();                             //重绘建筑图块
        }

        //在工具栏中绘制
        private void drawPic1(int x, int y, Image pic)
        {
            F.drawPic(g1, Rect1, x, y, pic, width);
        }

        private void drawNumber1(int x, int y, int num)
        {
            F.drawNumber(g1, Rect1, x, y, num, 9, width, width);
        }

        //对编辑区域坐标处的块数据进行解析
        private void drawSplit(int x, int y)
        {
            for (int i = 0; i < RL1.LineNum; i++)
                F.eraserPic(bg1, pictureBox1.Width, pictureBox1.Height, g1, RectTip, width, 0, i); //擦除所有图像
            
            int[] tmp = F.DataSplit(mapData[x][y]);    //先对块数据进行解析

            //步数炸弹块的值解析
            foreach (int i in tmp)
            {
                if (21 <= i && i <= 25)
                {
                    Point P = new Point(x, y);
                    if (!timeStep.ContainsKey(P)) timeStep.Add(P, 5);
                    panelStepTime.Visible = true;
                    textBoxStepTime.Text = timeStep[P].ToString();
                    break;
                }
                else panelStepTime.Visible = false;
            }

            for (int i = 0; i < tmp.Length; i++)
            {
                x = tmp[i] / 10 - 1;
                if (x == -1) continue;

                y = tmp[i] % 10 - 1;
                if (y == -1) continue;

                Image pic = Images[x][y];               //获取对应的图像
                F.drawPic(g1, RectTip, 0, i, pic, width);
            }
        }


        //在界面中绘制
        private void drawPic2(int x, int y, Image pic)
        {
            F.drawPic(g2, Rect2, x, y, pic, width, height);
        }

        //重绘编辑界面，坐标处的图像
        private void drawPic2(int x, int y)
        {
            if (x < 0) return;

            eraser2(x, y);                              //擦除坐标处的图像

            int data = mapData[x][y];                   //图块数据
            int[] tmp = F.DataSplit(data);              //先对块数据进行解析
            bool drawbirth = false;                     //标识是否绘制生成块图标

            //将第4行铁网数据移至最后
            for (int i = 0; i < tmp.Length; i++)
            {
                if (tmp[i] / 10 == 5)                   
                {
                    int tmp2 = tmp[i];
                    for (int i2 = i+1; i2 < tmp.Length; i2++) tmp[i2 - 1] = tmp[i2];
                    tmp[tmp.Length - 1] = tmp2;
                }
            }

            if (data != 0 && !F.Contains(73, data) && !F.Contains(74, data))
                F.drawPic_2(g2, Rect2, x, y, Resources.shade1, width, height); //绘制背景阴影

            Image pic;
            int px, py;
            int stepNum = -1;
            for (int i = 0; i < tmp.Length; i++)
            {
                //获取定时炸弹的定时步数
                if (21 <= tmp[i] && tmp[i] <= 25)
                {
                    Point P = new Point(x, y);
                    if (!timeStep.ContainsKey(P)) timeStep.Add(P, 5);
                    stepNum = timeStep[P];
                }

                if (tmp[i] == birthNum)
                {
                    drawbirth = true;
                    continue;
                }

                px = tmp[i] / 10 - 1;
                if (px == -1) return;

                py = tmp[i] % 10 - 1;

                //数据校验
                if (py >= Images[px].Length) py = -1;   //超出给定的图块数目范围，则清除
                if (py == -1)
                {
                    py = rnd.Next(Images[px].Length);   //未指定类型则随机生成
                    tmp[i] = (px + 1) * 10 + (py + 1);  //保存修正后的数据
                    mapData[x][y] = F.DataAdd(tmp);
                }

                pic = Images[px][py];                   //获取对应的图像

                //重绘
                if (tmp[i] == 73 || tmp[i] == 74)       //空存在块、阻挡块，绘制的图像与方格大小相同
                    F.drawPic_2(g2, Rect2, x, y, pic, width, height);
                else drawPic2(x, y, pic);                    
            }

            if (drawbirth) drawBirth(x, y);             //在坐标处绘制生成图标
            if (stepNum != -1)                          //绘制定时步数
                F.drawNumber(g2, Rect2, x, y, stepNum, 9, width, height);
        }

        //在编辑界面中绘制建筑图块
        private void drawBildings()
        {
            maxlayerNum = getCurMaxLayerNum();                      //建筑图层数
            setLayerNum(maxlayerNum);

            checkedListBox1.SelectedIndex = BuildPos.Layer;

            //绘制从VisPos.X 到 VisPos.X + 10 这11行
            int bottomRow = VisPos.X + 11 - 1;                        //可见区域最底行
            if (bottomRow > RL2.RowNum-1) bottomRow = RL2.RowNum-1;   //最大行位置

            RectsQueue.Clear();                                       //清空
            for (int l = 0; l < maxlayerNum; l++)
            {
                //if (!checkedListBox1.GetItemChecked(l)) continue;   //根据图层是否可见，进行相应绘制

                for (int i = 0; i < 11 && bottomRow - i >= 0; i++)               //显示可见区域的11行
                {
                    for (int j = 0; j < RL2.LineNum && j < VisPos.Y + 10; j++)   //显示可见区域的10列
                    {
                        Rectangle rect = drawPic3(bottomRow - i, j, l);//重绘界面中的建筑图块 

                        if (!rect.IsEmpty)
                        {
                            BiuildPos buildPos = new BiuildPos(bottomRow - i, j, l);
                            Rect_buildPos rectPos = new Rect_buildPos(rect, buildPos);

                            RectsQueue.Enqueue(rectPos);            //记录绘制的图块坐标区域
                        }
                    }
                }
            }
        }

        //在编辑界面中绘制建筑图块
        private void drawBildings_0()
        {
            maxlayerNum = getCurMaxLayerNum();                      //建筑图层数
            setLayerNum(maxlayerNum);

            for (int l = 0; l < maxlayerNum; l++)
            {
                if (!checkedListBox1.GetItemChecked(l)) continue;   //根据图层是否可见，进行相应绘制

                for (int i = RL2.RowNum-1; i >= 0; i--)
                {
                    for (int j = 0; j < RL2.LineNum; j++)
                        drawPic3(i, j, l);                          //重绘界面中的建筑图块    
                }
            }
        }

        //在编辑界面中，绘制指定图层中的建筑图块
        private Rectangle drawPic3(int x, int y, int layer)
        {
            Rectangle rect = new Rectangle();
            if (x < 0) return rect;

            Point P = new Point((int)((y + 0.5) * width + Rect2.Left), (int)((x + 0.5) * height + Rect2.Top));    //坐标方格的中点坐标
            Point off = new Point();
            Image pic;

            string dataIteam = buildsData[x][y];
            if (buildsData[x][y].Equals("")) return rect;      //若为空数据则返回     

            string[] iteams = dataIteam.Split('/');       //分割为单独的建筑图块项

            if (layer < iteams.Length)                    //该位置存在图层layer
            {
                if (iteams[layer].Equals("")) return rect;     //该层无数据
                string[] iteam = iteams[layer].Split('&');//分割数据项

                //建筑块属性解析
                int[] iteam1_4 = new int[4];
                float[] iteam5_6 = new float[2];
                iteam5_6[1] = 1;                          //默认缩放比例

                for(int i=0; i<iteam.Length; i++)
                {
                    if(i<iteam1_4.Length) 
                        iteam1_4[i] = F.ToInt(iteam[i]);
                    else if(i<iteam1_4.Length+iteam5_6.Length)
                        iteam5_6[i-iteam1_4.Length] = F.ToFloat(iteam[i]);
                }

                //更新建筑块数据
                if (iteam.Length < iteam1_4.Length + iteam5_6.Length)
                {
                    string str = ""; 
                    for(int i=0; i<iteam1_4.Length; i++) str += ((str.Equals("") ?  "" : "&" ) + iteam1_4[i]);
                    for (int i = 0; i < iteam5_6.Length; i++) str += "&" + iteam5_6[i];
                    buildsData[x][y] = str;
                }

                //获取对应属性的建筑图块
                pic = getBuild(iteam1_4[0], iteam1_4[3], iteam5_6[0], iteam5_6[1]);
                if (pic == null) return rect;

                //图像相对于方格中心对齐，外加偏移绘制量   
                off.X = -(pic.Width / 2) + iteam1_4[1];      
                off.Y = -(pic.Height / 2) + iteam1_4[2];
                g2.DrawImage(pic, P.X + off.X, P.Y + off.Y, pic.Width, pic.Height);

               rect = new Rectangle(P.X + off.X, P.Y + off.Y, pic.Width, pic.Height);

                //显示选中外边框
                //if (x == BuildPos.X && y == BuildPos.Y && layer == BuildPos.Layer)
                //    g2.DrawRectangle(Pens.Red, new Rectangle(P.X + off.X-2, P.Y + off.Y-2, pic.Width+4, pic.Height+4));
            }
            return rect;
        }

        //获取当前建筑的最大图层数
        private int getCurMaxLayerNum()
        {
            int maxLayer = 1;
            string[] tmp;
            for (int i = 0; i < RL2.RowNum; i++)
            {
                for (int j = 0; j < RL2.LineNum; j++)
                {
                    tmp = buildsData[i][j].Split('/');      //获取各坐标处的层数
                    if (maxLayer < tmp.Length) maxLayer = tmp.Length;  //记录更大层数值
                }
            }

            return maxLayer;
        }

        //在编辑界面中绘制建筑指定图层中的图块
        private void drawPic3_0(int x, int y, int layer)
        {
            Point P = new Point((int)((y + 0.5) * width), (int)((x + 0.5) * width));    //坐标方格的中点坐标
            Point off = new Point();
            Image pic;

            string dataIteam = buildsData[x][y];
            if (buildsData[x][y].Equals("")) return;      //若为空数据则返回     

            string[] iteams = dataIteam.Split('/');       //分割为单独的建筑图块项

            int[][] data = F.toArray2(dataIteam, '/', '&'); //转化为二维数组数据
            if (layer < data.Length)
            {
                int[] iteam = data[layer];                //获取对应图层建筑块数据

                pic = buildTiles[iteam[0]];               //获取对应的建筑图块
                off.X = -(pic.Width / 2) + iteam[1];      //图像相对于方格中心对齐，外加偏移绘制量   
                off.Y = -(pic.Height / 2) + iteam[2];

                g2.DrawImage(pic, P.X + off.X, P.Y + off.Y, pic.Width, pic.Height);
            }
        }

       
        //在编辑区坐标处，绘制birth图标
        private void drawBirth(int x, int y)
        {
            Point p = new Point(Rect2.X + y * width, Rect2.Y + x * height);      //行列位置转化为像素位置
            Image pic = Images[birthNum / 10 - 1][birthNum % 10 - 1];            //birth图标
            g2.DrawImage(pic, p.X + width / 2 + 1, p.Y + height / 2 - 2, width / 2 - 1, width / 2 - 1);
        }

        //图像擦除
        private void eraser1(int x, int y)
        {
            F.eraserPic(bg1, pictureBox1.Width, pictureBox1.Height, g1, Rect1, width, x, y);
        }
        private void eraser2(int x, int y)
        {
            F.eraserPic(bg2, pictureBox2.Width, pictureBox2.Height, g2, Rect2, width, height, x, y);
        }


        //在工具栏中的位置
        private void pictureBox1_MouseMove(object sender, MouseEventArgs e)
        {
            if (Rect1.Contains(e.Location))
            {
                toolsPos.Y = (e.X - Rect1.X) / width;
                toolsPos.X = (e.Y - Rect1.Y) / width;
            }
            else toolsPos.X = -1;   //表示鼠标不再工具栏中          
        }

        //工具栏中单击,记录选中的工具块位置
        private void pictureBox1_Click(object sender, EventArgs e)
        {
            if (toolsPos.X != -1)   //在工具栏中单击，则记录鼠标所在的块位置
            {
                toolSelect.X = toolsPos.X;
                toolSelect.Y = toolsPos.Y;

                //设置鼠标在编辑界面中显示图标
                pictureBox2.Cursor = mouseIcon[toolSelect.X][toolSelect.Y];

                if (toolsPos.Y >= Images[toolsPos.X].Length)
                {
                    toolBoxPos = 0;    //工具栏中无图标的块显示默认鼠标
                    return;
                }
                toolBoxPos = 1;         //单击了普通工具区
            }
        }


        Point StartP;
        Rectangle SelectRect = new Rectangle();
        bool mouseDrag = false;
        //记录在编辑界面中的位置
        private void pictureBox2_MouseMove(object sender, MouseEventArgs e)
        {
            if (Rect2.Contains(e.Location))
            {
                mapPos.Y = (e.X - Rect2.X) / width;
                mapPos.X = (e.Y - Rect2.Y) / height;

                labelRow.Text = "行：" + (mapPos.X + 1);
                labelLine.Text = "列：" + (mapPos.Y + 1);
            }
            else mapPos.X = -1;     //不在编辑界面中

            MousePoint = e.Location;//记录鼠标位置

            if (toolBoxPos == 1 || toolBoxPos == 3) return;//如果选择了基础块，或建筑块，则不响应
            //绘制虚线选择框
            if (e.Button == MouseButtons.Left && !MousePoint.Equals(StartP))
            {
                Point P = pictureBox2.PointToScreen(StartP);
                Size size = new Size(MousePoint.X - StartP.X, MousePoint.Y - StartP.Y);

                Rectangle rect = new Rectangle(P, size);

                if (!rect.Equals(SelectRect))
                {
                    mouseDrag = true;
                    ControlPaint.DrawReversibleFrame(SelectRect, this.BackColor, FrameStyle.Dashed);    //清除上次绘制

                    SelectRect = rect;
                    ControlPaint.DrawReversibleFrame(SelectRect, this.BackColor, FrameStyle.Dashed);    //重绘选区
                }
            }
        }

        private void pictureBox2_MouseDown(object sender, MouseEventArgs e)
        {
            StartP = e.Location;                //鼠标按下，记录其位置
            if (!controlPress) PosList.Clear(); //清空前一次选中的建筑块
        }

        private void pictureBox2_MouseUp(object sender, MouseEventArgs e)
        {
            if (mouseDrag)
            {
                mouseDrag = false;

                ControlPaint.DrawReversibleFrame(SelectRect, this.BackColor, FrameStyle.Dashed);    //清除绘制的选区

                if (!controlPress && PosList.Count == 0) draw();    //重新绘制界面

                Size Size = new Size(SelectRect.Size.Width, SelectRect.Size.Height);

                Rectangle rect = new Rectangle(StartP, Size);       //获取在编辑区中的选择区域
                if (rect.Width < 0) { rect.X += rect.Width; rect.Width *= -1; }
                if (rect.Height < 0) { rect.Y += rect.Height; rect.Height *= -1; }

                Rect_buildPos rectPos;
                for (int i = 0; i < RectsQueue.Count; i++)
                {
                    rectPos = RectsQueue.ElementAt(i);
                    if (rect.Contains(rectPos.Rect))                //选区包含 建筑块所在区域
                    {
                        g2.DrawRectangle(Pens.Red, rectPos.Rect);   //在建筑块周边绘制红色边框
                        if (!PosList.Contains(rectPos.buildPos))
                            PosList.Add(rectPos.buildPos);          //记录选中的建筑块
                        else
                        {
                            PosList.Remove(rectPos.buildPos);       //移除选中的建筑块
                            g2.DrawRectangle(Pens.White, rectPos.Rect);   //在建筑块周边绘制白色边框，表示取消选中
                        }
                    }
                }

                SelectRect = new Rectangle();   //清空
            }
        }


        //在编辑界面中单击，绘制对应的工具块到编辑界面中
        private void pictureBox2_Click(object sender, EventArgs e)
        {
            if (mouseDrag) return;              //如果为鼠标选区，则不执行单击功能
            if (mapPos.X == -1) return;         //鼠标不在编辑界面，则不执行操作

            clickTimeStep = new Point(mapPos.X, mapPos.Y);  //记录点中的定时炸弹块坐标

            if (toolBoxPos == 1)        //如果使用的是普通工具块
            {
                DataAdd(mapPos.X, mapPos.Y);    //将选中的工具块值合并到编辑区的块位置中

                drawPic2(mapPos.X, mapPos.Y);   //重绘坐标处的图像
                drawSplit(mapPos.X, mapPos.Y);  //对编辑区域坐标处的块数据进行解析
                drawBildings();                 //刷新建筑块的绘制
            }
            else if (toolBoxPos == 3)   //如果使用的是建筑工具区
            {
                //记录水平和垂直方向的偏移量
                if (!FixedRelativeH.Checked) textBoxOffX.Text = (MousePoint.X - (int)((mapPos.Y + 0.5) * width) - Rect2.Left).ToString();
                if (!FixedRelativeV.Checked) textBoxOffY.Text = (MousePoint.Y - (int)((mapPos.X + 0.5) * height) -Rect2.Top).ToString();

                //添加建筑块属性到对应坐标处
                string str = getBuildAttr();     //获取属性数据
                if (str.Equals("")) return;
                buildsData[mapPos.X][mapPos.Y] += ((buildsData[mapPos.X][mapPos.Y].Equals("") ? "" : "/") + str); //项分割符号

                //记录该建筑块在编辑区中的位置
                string[] tmp = buildsData[mapPos.X][mapPos.Y].Split('/');   
                BuildPos.set(mapPos.X, mapPos.Y, tmp.Length-1);

                if(!checkBoxSelectBuid.Checked) drawBildings(); //刷新建筑块的绘制
                timerDelayDoing(2, 30);                         //更新建筑块显示
            }
            else if (toolBoxPos == 0)    //进行图块的解析
            {
                drawSplit(mapPos.X, mapPos.Y);              //对编辑区域坐标处的块数据进行解析

                string[] tmp = buildsData[mapPos.X][mapPos.Y].Split('/');

                //若与上一次选中的坐标相同，则依次取前一图层； 否则取最后一层
                if (BuildPos.X == mapPos.X && BuildPos.Y == mapPos.Y) BuildPos.Layer--;
                else BuildPos.set(mapPos.X, mapPos.Y, tmp.Length - 1);
                if (BuildPos.Layer < 0) BuildPos.Layer = tmp.Length - 1;

                if (!tmp[BuildPos.Layer].Equals(""))        //如果选中建筑块存在
                {
                    timerDelayDoing(2, 30);                 //更新建筑块显示
                }

                //显示鼠标单击坐标处的图层数，和当前选中的图层位置
                for (int i = 0; i < maxlayerNum; i++)
                    checkedListBox1.SetItemChecked(i, (i < tmp.Length));
                //checkedListBox1.SelectedIndex = tmp.Length - 1;
            }
            groupBoxBuild.Text = "建筑块(" + (mapPos.X+1) + "," + (mapPos.Y+1) + ")";
        }

        
        

        //将数据data 合并到数据块x,y中，或执行功能块的对应功能
        private void DataAdd(int x, int y)
        {
            if (toolSelect.X == -1) return;

            int data = (toolSelect.X + 1) * 10 + (toolSelect.Y + 1);    //按照工具块的位置，生成块标识值

            if (data == eraserNum)
            {
                if (ToolStripMenuItemEraserMode2.Checked)               //擦除建筑块
                    eraserBuildsData(x, y);
                else mapData[x][y] = 0;                                 //执行橡皮擦功能，擦除对应块位置处的数据
            }
            else if (data == shadeNum || data == wallNum)               //空块或者墙块，清除原来的块数据并添加当前块值
                mapData[x][y] = data;
            else
            {
                if (mapData[x][y] == shadeNum || mapData[x][y] == wallNum)  //若当前块为空块或者墙块则被替换
                    mapData[x][y] = data;
                else mapData[x][y] = F.DataAdd(data, mapData[x][y]);        //合并数据到块数据中
            }

            //若使用橡皮块、阴影快、墙块替换当前定时炸弹块，则清除当前块对应数据
            if (data == eraserNum || data == shadeNum || data == wallNum)
                if (timeStep.ContainsKey(clickTimeStep)) timeStep.Remove(clickTimeStep);
        }

        //对坐标处的块，进行数据解析
        private int[] DataAnalytical(int x, int y)
        {
            return F.DataSplit(mapData[x][y]);
        }

        //刷新界面的显示
        private void btnRefreash_Click(object sender, EventArgs e)
        {
            timerDraw.Enabled = true;                       //延迟绘制界面
        }

        //导出编辑区的数据到文件
        private void btnOutFile_Click(object sender, EventArgs e)
        {
            OutFileProcess0(false);  //导出编辑的关卡数据
        }

        //导出当前编辑的关卡数据
        private void OutFileProcess(bool mute)
        {
            try { OutFileProcess0(mute);}
            catch (Exception) {}
        }
        private void OutFileProcess0(bool mute)
        {
            //生成Json数据项
            string[] JsonIteams = 
            { 
                F.ToJsonIteam("EditorName", "营救宠物"),        //编辑器名称
                F.ToJsonIteam("mapData", mapData),              //图块数据
                F.ToJsonIteam("tileProbility", getProbility()), //概率数据
                F.ToJsonIteam("checkState", getCheckState()),   //复选框数据
                F.ToJsonIteam("textInfo", getSetInfo()),        //设置信息
                F.ToJsonIteam("buildsData", buildsData),        //建筑图块数据
                F.ToJsonIteam("timeStep", getTimeStepData()),   //定时炸弹步数值
                F.ToJsonIteam("otherInfo", (TargetWidth/(double)width).ToString())
            };
            //生成Json对象串
            string JsonObj = F.ToJsonObj(JsonIteams);

            //保存数据到文件
            string name;
            if (checkReplaceNative.Checked)
            {
                name = (OpendFilesName != null) ? OpendFilesName[curFilePos] : "";
                name = F.SaveToNativeFile(JsonObj, name, mute);
            }
            else
            {
                name = curFileName.Text.Trim();              //保存文件名
                name = F.SaveToFile(JsonObj, name, mute);    //将Json数据保存到文件中,并记录文件名
            }


            //相关信息设置
            setCurFileName(name);                            //设置当前打开的文件名称

            //当前文件位置指向保存的文件
            if (OpendFilesName == null)
                OpendFilesName = new string[] { name };
            else OpendFilesName[curFilePos] = name;

            showJumpInfo();                        //显示关卡数据跳转相关信息     
        }


        //重置编辑数据为初始值，新建关卡编辑
        private void reset(object sender, EventArgs e)
        {
            if (OpendFilesName == null) return;     //若当前未打开任何文件则无需新建

            //数据初始化
            initMapData();
            initProbility();
            initBuildData();
            timeStep.Clear();

            //重新绘制
            reDraw(); 

            //创建一个空文件名添加到文件名数组中
            string[] str = new string[OpendFilesName.Length + 1];
            Array.Copy(OpendFilesName, str, OpendFilesName.Length);
            str[str.Length - 1] = "";
            OpendFilesName = str;

            curFileName.Text = "";
            this.Text = "营救宠物 关卡编辑 - 新建";
            curFilePos = str.Length - 1;

            //新建关卡编辑后，在保存数据前不可跳转下一数据
            panelJump.Visible = false;
        }

        //---------------------------------------------------------------------------------------------------
        //文件拖入、放下窗体处理事件
        //---------------------------------------------------------------------------------------------------
        private void Form1_DragEnter(object sender, DragEventArgs e)
        {
            F.dragEnter(e);
        }
        private void Form1_DragDrop(object sender, DragEventArgs e)
        {
            string filesName = F.dragDrop(e);      //拖入窗体的文件放下
            OpendFilesName = filesName.Split(';'); //分割为所有的文件名

            paint(0);                              //在编辑界面中显示第一个文件
            showJumpInfo();                        //显示关卡数据跳转相关信息       
        }

        //在编辑界面中，显示打开的第pos个关卡文件
        private void paint(int pos)
        {
            try { paint0(pos); }
            catch (Exception ex) { MessageBox.Show("关卡数据格式有误！"); }
        }
        private void paint0(int pos)
        {
            curFilePos = pos;
            if (OpendFilesName == null) return;
            if (curFilePos < 0) curFilePos = OpendFilesName.Length - 1;
            if (curFilePos > OpendFilesName.Length - 1) curFilePos = 0;

            //相关信息设置
            string fileName = OpendFilesName[curFilePos];               //获取文件完整路径
            setCurFileName(fileName);                                   //显示当前打开的文件名称

            //从文件中读取关卡数据
            string content = F.ToString(fileName);                      //获取curFilePos位置处的文件内容

            //图块数据获取
            string mapdata = F.getJsonNodeData(content, "mapData");     //获取Json串对象，节点"mapData"的数据
            mapData = F.ToArray2(mapdata);                              //转化为二维数组数据

            RL2.RowNum = mapData.Length;                                //获取行列数
            RL2.LineNum = mapData[0].Length;
            Rect2 = new Rectangle(border, border, width * RL2.LineNum, height * RL2.RowNum);   //更新编辑区域的范围
            textBoxRow.Text = RL2.RowNum.ToString();
            textBoxLine.Text = RL2.LineNum.ToString();


            //reDraw();                                                   //刷新界面的显示

            //图块概率值设置
            string strProbility = 
                F.getJsonNodeData(content, "tileProbility");            //获取Json串对象，节点"tileProbility"的数据
            int[][] tileProbility = F.ToArray2(strProbility);           //转化为二维数组数据
            setProbility(tileProbility);                                //设置获取的数据到概率编辑界面中
            
            //复选框、其他设置输入框信息设置
            string checkData = F.getJsonNodeData(content, "checkState");//获取Json串对象，节点"checkState"的数据
            int[] checkState = F.ToArray1(checkData);                   //转化为一维数组数据
            setCheckState(checkState);

            string textData = F.getJsonNodeData(content, "textInfo");   //获取Json串对象，节点"textInfo"的数据
            string[] textInfo = textData.Split(',');                    //转化为一维数组数据
            setTextInfo(textInfo);

            //获取建筑图块数据
            string buildsStr = F.getJsonNodeData(content, "buildsData");//获取Json串对象，节点"buildsData"的数据
            buildsData = F.Split(buildsStr, ';', ',');

            //获取定时炸弹步数值
            string data = F.getJsonNodeData(content, "timeStep");       //获取Json串对象，定时炸弹步数值
            setTimeStepData(F.ToArray2(data));                          //设置定时炸弹步数值

            draw();//刷新界面的显示
        }

        //设置当前打开的文件名称
        private void setCurFileName(string fileName)
        {
            if (fileName.Equals("") || fileName == null) return;

            String name = System.IO.Path.GetFileNameWithoutExtension(fileName);   //文件名
            this.Text = "营救宠物 关卡编辑 - " + name;
            curFileName.Text = name;
        }

        //---------------------------------------------------------------------------------------------------
        //关卡位置跳转功能
        //---------------------------------------------------------------------------------------------------
        private void JumpFunction(int n)
        {
            int pos = curFilePos;
            int allNum = OpendFilesName.Length;     //打开关卡文件总数

            //获取要跳转的位置
            try { pos = Int32.Parse(textJump.Text.Trim()); }
            catch (Exception e) {}

            if (n == 1) paint(pos-1);               //跳转到指定的文件
            else if (n == 2) paint(curFilePos - 1); //跳转前一个
            else if (n == 3) paint(curFilePos + 1); //跳转下一个
            else if (n == 4) paint(curFilePos - (int)(allNum / 5)); //跳转前一页
            else if (n == 5) paint(curFilePos + (int)(allNum / 5)); //跳转下一页

            showJumpInfo();
        }
        //显示跳转相关信息
        private void showJumpInfo()
        {
            int allNum = OpendFilesName.Length;     //打开关卡文件总数
            panelJump.Visible = allNum > 1;         //设置跳转界面是否可见
            if (!panelJump.Visible) return;

            textJump.Text = (curFilePos + 1).ToString();    //显示当前文件位置
            labelJump.Text = "/" + allNum + "项";           //总文件数
        }
        private void btnJump_Click(object sender, EventArgs e)
        { JumpFunction(1); }
        private void btnPre_Click(object sender, EventArgs e)
        { JumpFunction(2); }
        private void btnNext_Click(object sender, EventArgs e)
        { JumpFunction(3); }
        private void btnPgUp_Click(object sender, EventArgs e)
        { JumpFunction(4); }
        private void btnPgDn_Click(object sender, EventArgs e)
        { JumpFunction(5); }


        //---------------------------------------------------------------------------------------------------
        // 其他设置信息，所有复选框checks选择信息、所有文本框texts信息
        //---------------------------------------------------------------------------------------------------
        CheckBox[] checks;
        TextBox[] texts;
        private void InitSetting()
        {
            //原有复选框控件
            CheckBox[] checksNative = new CheckBox[] { checkTargetDistance, checkBoxRndCtrl1, checkBoxRndCtrl2, checkBoxRndCtrl3, checkBoxRndCtrl4, checkBoxFixedStyle, checkNumControl, checkBoxRndCtrl5, checkBoxBirthStart };
            
            //所有复选框控件
            checks = new CheckBox[checksNative.Length + checkLines.Length];
            for (int i = 0; i < checksNative.Length; i++) checks[i] = checksNative[i];                      //【0，8】
            for (int i = 0; i < checkLines.Length; i++) checks[i + checksNative.Length] = checkLines[i];    //【9，17】

            texts = new TextBox[] 
            { 
                textBoxGameMode, textBoxNum, textBoxNum21, textBoxNum22, textBoxNum23, textBoxNum24, textBoxNum25,
                textBoxTargetScore1, textBoxTargetScore2, textBoxTargetScore3, textBoxStepLimit, textBoxTargetDistance,
                textBoxVisibleRowNum, textBoxNumGenerate, textBoxBirthStart
            };
        }

        //获取所有复选框的选中状态
        private int[] getCheckState()
        {
            int[] data = new int[checks.Length];
            for (int i = 0; i < checks.Length; i++)
                data[i] = checks[i].Checked ? 1 : 0;
            return data;
        }

        //获取所有复选框的选中状态
        private string getCheckState2()
        {
            //int[] data = new int[checks.Length];
            string str = "";
            for (int i = 0; i < checks.Length; i++)
            {
                str += checks[i].Checked ? "1" : "0";
                if (i < checks.Length - 1) str += ",";
            }
            return str;
        }
        //根据checkState设置所有复选框的选中状态
        private void setCheckState(int[] checkState)
        {
            for (int i = 0; i < checks.Length; i++)
            {
                if (i < checkState.Length) checks[i].Checked = (checkState[i] == 1);
                else checks[i].Checked = false;
            }
        }

        //获取设置信息
        private string getSetInfo()
        {
            return getTextNumInfo(texts);
        }
        //获取所有输入框的信息，已数值形式进行解析
        private string getTextNumInfo(TextBox[] textBox)
        {
            string str = "";
            for (int i = 0; i < textBox.Length; i++)
            {
                int num = 0;
                try { num = Int32.Parse(textBox[i].Text.Trim()); }
                catch (Exception e) { };
                str += num.ToString();

                if (i < textBox.Length - 1) str += ",";
            }
            return str;
        }

        //获取所有输入框的信息，以字符串形式进行解析
        private string getTextInfo(TextBox[] texts)
        {
            string str = "";
            for (int i = 0; i < texts.Length; i++)
            {
                str += texts[i].Text.Trim();
                if (i < texts.Length - 1) str += ",";
            }
            return str;
        }
        //设置所有输入框的信息
        private void setTextInfo(string[] strInfo)
        {
            //设置游戏的编辑模式
            if (strInfo != null) comboBoxGameMode.SelectedIndex = Int32.Parse(strInfo[0]);

            //载入其他信息
            for (int i = 0; i < texts.Length; i++)
            {
                if (i < strInfo.Length) texts[i].Text = strInfo[i];
                else texts[i].Text = "";
            }
        }


        //---------------------------------------------------------------------------------------------------
        // 弹出菜单栏，控制对应控件框是否可见
        //---------------------------------------------------------------------------------------------------

        //根据控件是否可用设置行概率输入框是否可见
        private void CheckSetProbility_CheckedChanged(object sender, EventArgs e)
        {
            setRowInputVisible(CheckSetProbility.Checked);
            timerDelayDoing(1); //设置各属性块概率是否可输入
        }
        //设置行列数输入框是否可见
        private void checkSetRL2_CheckedChanged(object sender, EventArgs e)
        {
            panelSetRL2.Visible = checkSetRL2.Checked; 
        }


        //---------------------------------------------------------------------------------------------------
        //其他处理事件
        //---------------------------------------------------------------------------------------------------

        //滚动条滚动事件
        private void EditViewPannel_Scroll(object sender, ScrollEventArgs e)
        {
            timerDraw.Enabled = false;
            timerDraw.Interval = 300;
            timerDraw.Enabled = true;

            //编辑区的显示起点坐标位置，随滚动条的滚动而变化
            Point P = EditViewPannel.AutoScrollPosition;    

            VisPos.X = (-P.Y - Rect2.Y) / height;
            VisPos.Y = (-P.X - Rect2.X) / width;

            //checkBoxSelectBuid.Text = VisPos.ToString();
        }

        //应用设置行列数数值
        private void btnSetRL2_Click(object sender, EventArgs e)
        {
            //获取设置的行列数值
            int num;
            try { num = Int32.Parse(textBoxRow.Text.Trim()); }
            catch (Exception ex) { num = 0; }
            if (num > 0) RL2.RowNum = num;

            try { num = Int32.Parse(textBoxLine.Text.Trim()); }
            catch (Exception ex) { num = 0; }
            if (num > 0) RL2.LineNum = num;

            reBuildEditor(true);                        //根据设定的行列数重新构建编辑界面

            checkSetRL2.Checked = false;                //
        }

        //根据新的行列数重新构建编辑界面
        private void reBuildEditor(bool rebuid)
        {
            Rect2 = new Rectangle(border, border, width * RL2.LineNum, height * RL2.RowNum);   //更新编辑区域的范围
            if (rebuid)
            {
                mapData = rebuild(mapData, RL2.RowNum, RL2.LineNum);            //数据转存，构建新的数组
                buildsData = rebuild(buildsData, RL2.RowNum, RL2.LineNum);      //建筑数据转存
            }
            reDraw();                                                           //界面重绘
        }

        //按给定行列数，重新构建数组，尽量保留数组中的原有数据
        private int[][] rebuild(int[][] data, int Row, int Line)
        {
            int[][] tmp = new int[Row][];           //创建二维空间
            int minRow = Row < data.Length ? Row : data.Length;                 //取较小的行数
            for (int i = 0; i < Row; i++)
            {
                tmp[i] = new int[Line];             //创建一维空间

                if (i >= minRow) continue;            //超出行范围

                int minLine = Line < data[i].Length ? Line : data[i].Length;    //取较小的列数
                for (int j = 0; j < minLine; j++)
                {
                    tmp[i][j] = data[i][j];         //数据转存到tmp中
                }
            }

            return tmp;                             //返回新的数组
        }

        //按给定行列数，重新构建数组，尽量保留数组中的原有数据
        private string[][] rebuild(string[][] data, int Row, int Line)
        {
            string[][] tmp = new string[Row][];     //创建二维空间
            for (int i = 0; i < Row; i++)
            {
                tmp[i] = new string[Line];          //创建一维空间
                for (int j = 0; j < Line; j++)
                {
                    tmp[i][j] = "";
                }
            }

            int minRow = Row < data.Length ? Row : data.Length; //取较小的行数
            for (int i = 0; i < Row; i++)
            {
                if (i >= minRow) continue;          //超出行范围

                int minLine = Line < data[i].Length ? Line : data[i].Length;    //取较小的列数
                for (int j = 0; j < minLine; j++)
                {
                    tmp[i][j] = data[i][j];         //数据转存到tmp中
                }
            }

            return tmp;                             //返回新的数组
        }

        //游戏模式变动事件
        private void comboBoxGameMode_SelectedIndexChanged(object sender, EventArgs e)
        {
            //设置界面的显示内容
            //Panel[] panels = { panelGameMode, panelNum, panelNum2, panelTargetScore, panelStepLimit, panelTargetDistance, panelVisibleRowNum };

            int index = comboBoxGameMode.SelectedIndex;//选择模式
            textBoxGameMode.Text = index.ToString();   //模式值变动
            AutoLayoutPanels(index);                   //根据模式设置控件
            setModeExplain(index);                     //设置模式说明信息
        }

        //动态布局设置Panels，根据游戏模式
        private void AutoLayoutPanels(int index)
        {
            //设置界面的显示内容
            Panel[] panels = { panelGameMode, panelNum, panelNum2, panelTargetScore, panelStepLimit, panelTargetDistance, panelVisibleRowNum, panelBirthStart };
            bool[][] visible = 
            {
                new bool[]{ true, false, true, true, true, true, true, true},
                new bool[]{ true, true, false, true, true, true, true, true },
                new bool[]{ true, false, true, true, true, false, true, true },
                new bool[]{ true, false, false, true, true, false, true, true },
                new bool[]{ true, false, false, true, true, false, true, true },
                new bool[]{ true, false, true, true, true, true, true, true },
                new bool[]{ true, false, false, true, true, false, true, true }
            };

            Point P = new Point(panels[0].Left, panels[0].Top); //获取第一个控件的位置
            for (int i = 0; i < panels.Length; i++)
            {
                panels[i].Visible = visible[index][i];          //根据游戏模式设置控件可见状态
                if (panels[i].Visible)                          //如果控件可见
                {
                    panels[i].Left = P.X;
                    panels[i].Top = P.Y;

                    P.Y += panels[0].Height;
                }

            }

            //控制控件checkNumControl的位置
            checkNumControl.Top = 61;
            if (index == 1)
            {
                checkNumControl.Visible = true;
                checkNumControl.Left = 146;
            }
            else if (index == 0 || index == 5)
            {
                checkNumControl.Visible = true;
                checkNumControl.Left = 197;
            }
            else checkNumControl.Visible = false;

            //修改时间模式和步数模式对应的显示信息
            if (index == 6) labelStepLimit.Text = "时间限制：";
            else labelStepLimit.Text = "步数限制：";
        }
        //根据游戏模式，设置对应的模式说明信息
        private void setModeExplain(int index)
        {
            string[] info = { "收集一定数量的水果即可获胜", "消除一定数量的铁丝网", "消除一定数量的某色或者某几色普通块", "获得一定分数,即为获胜", "完美消除，消除所有块才可获胜", "收集一定量的特殊块‘饼干’", "规定时间内,获得一定分数,即为获胜", };
            labelModeExplain.Text = info[index];
        }

        //获取鼠标的位置
        private void pictureBoxBuildings_MouseMove(object sender, MouseEventArgs e)
        {
            MousePoint = e.Location;
        }
        //单击图片中的图块，获取对应的建筑块图像
        private void pictureBoxBuildings_Click(object sender, EventArgs e)
        {
            //选中建筑块中的对应建筑块
            buildIndex = selectBuildTile(MousePoint, Resources.buildings, buildRects);

            //若未获取到建筑块，则返回
            if (buildIndex == -1) return;

            toolBoxPos = 3;             //单击了建筑图块区
            setBuildAttr(buildIndex);   //设置选中建筑块为默认属性
        }

        

        //判断鼠标单击位置，是否选中对应的建筑块区域
        private int selectBuildTile(Point mouseP, Image pic, Rectangle[] Rects)
        {
            Image bg = Resources.buildings;                 //背景图像
            Rectangle boxRec = new Rectangle(0, 0, pictureBoxBuildings.Width, pictureBoxBuildings.Height);
            Rectangle picRec = new Rectangle(0, 0, bg.Width, bg.Height);

            //将在编辑界面中的鼠标位置对应转化为在背景图像中的位置
            float reSizeW = picRec.Width / (float)boxRec.Width;
            float reSizeH = picRec.Height / (float)boxRec.Height;
            Point P2 = new Point((int)(mouseP.X * reSizeW), (int)(mouseP.Y * reSizeH));

            //判断鼠标单击处是否存在建筑块
            for (int i = 0; i < Rects.Length; i++)
                if (Rects[i].Contains(P2)) return i; 
            return -1;    //未选中建筑块
        }

        

        //初始化所有建筑块对应的区域
        private void initRects()
        {
            string[] attr = { "n", "x", "y", "w", "h" };
            //string[] attr = { "x", "y", "w", "h" };

            string[][] tmp = F.ReadXML_NodesAttrribute2(Resources.buildingsSiteFile, "TextureAtlas/sprite", attr);
            //string[][] tmp = F.ReadXML_NodesAttrribute("buildings.xml", "TextureAtlas/sprite", attr);
            buildRects = convertToRect(tmp);    
        }

        //将数组中的数据转换为区域数组
        private Rectangle[] convertToRect(string[][] data)
        {
            Rectangle[] Rects = new Rectangle[data.Length];

            int[] n = new int[4];
            for (int i = 0; i < data.Length; i++)
            {
                for (int j = 0; j < 4; j++)
                    n[j] = Int32.Parse(data[i][j+1].Trim());        //转化为数值
                Rects[i] = new Rectangle(n[0], n[1], n[2], n[3]);   //创建新的区域

                buildPicMap += (i == 0 ? "" : ",") + data[i][0];    //添加到映射
            }

            return Rects;
        }

        //初始化所有建筑图块
        private void initBuildTiles()
        {
            Image bg = Resources.buildings;                     //背景图像
            Rectangle boxRec = new Rectangle(0, 0, pictureBoxBuildings.Width, pictureBoxBuildings.Height);
            Rectangle picRec = new Rectangle(0, 0, bg.Width, bg.Height);

            //将在编辑界面中的鼠标位置对应转化为在背景图像中的位置
            float reSizeW = picRec.Width / (float)boxRec.Width;
            float reSizeH = picRec.Height / (float)boxRec.Height;

            //创建建筑块图像
            buildTiles = new Bitmap[buildRects.Length];
            for (int i = 0; i < buildRects.Length; i++)
            {
                buildTiles[i] = F.GetRect(bg, buildRects[i]);   //获取建筑块的图像

                Rectangle Rect = new Rectangle(0, 0, (int)(buildTiles[i].Width / reSizeW), (int)(buildTiles[i].Height / reSizeH ));
                buildTiles[i] = F.shrinkTo(buildTiles[i], Rect);//将图像缩小到建筑图块区对应大小
            }
        }

        //初始化建筑层数据
        private void initBuildData()
        {
            buildsData = new string[RL2.RowNum][];
            for (int i = 0; i < RL2.RowNum; i++)
            {
                buildsData[i] = new string[RL2.LineNum];
                for (int j = 0; j < RL2.LineNum; j++)
                {
                    buildsData[i][j] = "";
                }
            }
        }

        //将当前编辑的建筑块层位置上移
        private void button1_Click(object sender, EventArgs e)
        {
            string tmp = "";
            string[] iteams = buildsData[BuildPos.X][BuildPos.Y].Split('/');    //获取该坐标处的所有建筑块数据

            if (BuildPos.Layer < 0 || BuildPos.Layer > iteams.Length - 1) return; //不存在该层

            if (BuildPos.Layer == iteams.Length - 1)        //添加一个空层
            {
                iteams[iteams.Length - 1] = "/" + iteams[iteams.Length - 1];            
            }
            else //与后一个图层交换
            {
                string tmp2 = iteams[BuildPos.Layer];
                iteams[BuildPos.Layer] = iteams[BuildPos.Layer + 1];
                iteams[BuildPos.Layer + 1] = tmp2;
            }
            BuildPos.Layer++;   //记录新的图层位置

            //重新合并为数据
            for (int i = 0; i < iteams.Length; i++)
                tmp += ((i==0 ? "": "/") + iteams[i]);

            buildsData[BuildPos.X][BuildPos.Y] = tmp; //保存新的数据

            drawMap();              //重绘界面显示
        }

        //将当前编辑的建筑块层位置下移
        private void button2_Click(object sender, EventArgs e)
        {
            string tmp = "";
            string[] iteams = buildsData[BuildPos.X][BuildPos.Y].Split('/');    //获取该坐标处的所有建筑块数据

            if (BuildPos.Layer <= 0 || BuildPos.Layer > iteams.Length-1) return;//不存在 或已处于最底层

            else //与前一个图层交换
            {
                string tmp2 = iteams[BuildPos.Layer];
                iteams[BuildPos.Layer] = iteams[BuildPos.Layer - 1];
                iteams[BuildPos.Layer - 1] = tmp2;
            }
            BuildPos.Layer--;   //记录新的图层位置

            //重新合并为数据
            for (int i = 0; i < iteams.Length; i++)
            {
                if (i == iteams.Length - 1 && iteams[iteams.Length - 1].Equals("")) break;  //若最后一个图层为空，则不添加
                else  tmp += ((i == 0 ? "" : "/") + iteams[i]);
            }

            buildsData[BuildPos.X][BuildPos.Y] = tmp; //保存新的数据

            drawMap();              //重绘界面显示
        }

        //擦除坐标处，可见的建筑图块数据
        private void eraserBuildsData(int x, int y)
        {
            string tmp = "";
            string str = buildsData[x][y];
            if (str.Equals("")) return;

            string[] iteams = str.Split('/');
            int j = 0;
            for (int i = 0; i < iteams.Length; i++)
            {
                if (checkedListBox1.GetItemChecked(i)) continue;    //擦除显示的图层数据

                tmp += ((j==0 ? "" : "/") + iteams[i]);
                j++;
            }

            buildsData[x][y] = tmp;       //保存新的数据
            drawMap();              //重绘界面显示
        }

        //创建num个check控件，控制建筑图层的可见性
        private void setLayerNum(int num)
        {
            if (checkedListBox1.Items.Count > num)
            {
                for (int i = checkedListBox1.Items.Count - 1; i >= num; i--)
                    checkedListBox1.Items.RemoveAt(i);
            }
            else
            {
                for (int i = checkedListBox1.Items.Count + 1; i <= num; i++)
                    checkedListBox1.Items.Add("图层" + i, true);
            }
        }

        private void checkedListBox1_ItemCheck(object sender, ItemCheckEventArgs e)
        {
            //reDraw();
        }

        private void checkedListBox1_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (BuildPos.Layer != checkedListBox1.SelectedIndex)
            {
                BuildPos.Layer = checkedListBox1.SelectedIndex;
                timerDelayDoing(2, 30);
            }
        }


        //建筑块属性操作

        //应用对建筑块属性的修改
        private void button1_Click_1(object sender, EventArgs e)
        {
            if (toolBoxPos != 0 && toolBoxPos != 3) return; //仅在编辑区域单击选择建筑图块后，才可修改图块属性

            string iteam = textBoxBuildIndex.Text.Trim() + "&" + textBoxOffX.Text.Trim() + "&" + textBoxOffY.Text.Trim();  //设置建筑块属性
            iteam += ("&" + comboBoxMirror.SelectedIndex + "&" + comboBoxRotate.Text.Trim() + "&" + textBoxShrink.Text.Trim());

            int x = BuildPos.X, y = BuildPos.Y, layer = BuildPos.Layer;

            string dataIteam = buildsData[x][y];            //获取图块数据
            if (buildsData[x][y].Equals("")) return;        //若为空数据则返回     

            string[] iteams = dataIteam.Split('/');         //分割为单独的建筑图块项
            if (0 <= layer && layer < iteams.Length)        //该位置存在图层layer
            {
                iteams[layer] = iteam;                      //修改属性
                buildsData[x][y] = F.ToString(iteams, "/"); //保存到建筑数据
            }

            reDraw();       //刷新界面显示
        }

        //删除选中的建筑块
        private void button2_Click_1(object sender, EventArgs e)
        {
            if (toolBoxPos != 0 && toolBoxPos != 3) return;    //仅在编辑区域单击选择建筑图块后，才可修改图块属性

            Boolean needRedraw = false;
            if (deletBuild(BuildPos)) needRedraw = true;

            if (PosList.Count > 0)
            {
                foreach (BiuildPos iteam in PosList) if (deletBuild(iteam)) needRedraw = true;
                PosList.Clear();
            }

            gBuild.Clear(pictureBoxbuild.BackColor);        //清除属性界面建筑块的显示
            if(needRedraw) reDraw();       //刷新界面显示
        }

        //删除指定位置处的建筑块
        private Boolean deletBuild(BiuildPos BuildPos)
        {
            int x = BuildPos.X, y = BuildPos.Y, layer = BuildPos.Layer;

            string dataIteam = buildsData[x][y];            //获取图块数据
            if (buildsData[x][y].Equals("")) return false;  //若为空数据则返回     

            Boolean needRedraw = false;
            string[] iteams = dataIteam.Split('/');         //分割为单独的建筑图块项
            if (0 <= layer && layer < iteams.Length)        //该位置存在图层layer
            {
                needRedraw = !iteams[layer].Equals("");     //删除的建筑块存在时，需重新绘制界面
                iteams[layer] = "";                         //清空属性数据

                //判断最后一个非空层的位置
                int l = iteams.Length - 1;
                for (; l >= 0; l--) if (!iteams[l].Equals("")) break;

                //数据转存到新的数组
                string[] iteams2 = null;
                if (++l > 0)
                {
                    iteams2 = new string[l];
                    Array.Copy(iteams, iteams2, l);
                }

                buildsData[x][y] = F.ToString(iteams2, "/");//保存到建筑数据
            }
            return needRedraw;
        }

        //获取属性区，建筑图块
        private Bitmap getBuild()
        {
            int picIndex = F.ToInt(textBoxBuildIndex.Text.Trim());
            Image buildTile = buildTiles[picIndex];            //获取图像

            Bitmap pic = F.ToBitmap(buildTile);

            //镜像
            if (comboBoxMirror.SelectedIndex == 2) pic = F.FlipX(pic);
            else if (comboBoxMirror.SelectedIndex == 1) pic = F.FlipY(pic);

            //缩放
            float reSize = 1;
            reSize = F.ToFloat(textBoxShrink.Text.Trim(), 1);
            if (reSize != 1 && reSize != 0) pic = F.shrinkTo(pic, reSize);

            //旋转
            float angle = F.ToFloat(comboBoxRotate.Text.Trim(), 0);
            if (angle != 0) pic = F.KiRotate(pic, angle);

            return pic;
        }

        //获取对应属性的建筑图块
        private Bitmap getBuild(int picIndex, int mirror, float rotate, float shrink)
        {
            if (picIndex == -1 || picIndex>buildTiles.Length) return null;
            Bitmap pic = F.ToBitmap(buildTiles[picIndex]);  //获取图像

            //镜像
            if (mirror == 2) pic = F.FlipX(pic);
            else if (mirror == 1) pic = F.FlipY(pic);

            //缩放
            if (shrink != 1) pic = F.shrinkTo(pic, shrink);

            //旋转
            if (rotate != 0) pic = F.KiRotate(pic, rotate);

            return pic;
        }


        //设置建筑块默认属性值到对应位置
        private void setBuildAttr(int buildIndex)
        {
            if(buildIndex==-1) return;
            setBuildAttr(buildIndex, 0, 0, 0, 0, 1);
        }

        //设置待编辑的建筑块数据
        private void setBuildAttr(int x, int y, int layer)
        {
            gBuild.Clear(pictureBoxbuild.BackColor);        //清除属性界面建筑块的显示

            //drawPic3(x, y, l);                            //重绘界面中的建筑图块 
            if(checkBoxSelectBuid.Checked) drawMap();
            //drawBildings();                               //重绘所有建筑块

            if (layer < 0) return;

            string dataIteam = buildsData[x][y];
            if (buildsData[x][y].Equals("")) return;      //若为空数据则返回     

            string[] iteams = dataIteam.Split('/');       //分割为单独的建筑图块项

            if (layer < iteams.Length)                    //该位置存在图层layer
            {
                if (iteams[layer].Equals("")) return;     //该层无数据
                string[] iteam = iteams[layer].Split('&');//分割数据项

                //建筑块属性解析
                int[] iteam1_4 = new int[4];
                float[] iteam5_6 = new float[2];
                iteam5_6[1] = 1;                          //默认缩放比例

                for (int i = 0; i < iteam.Length; i++)
                {
                    if (i < iteam1_4.Length)
                        iteam1_4[i] = F.ToInt(iteam[i]);
                    else if (i < iteam1_4.Length + iteam5_6.Length)
                        iteam5_6[i - iteam1_4.Length] = F.ToFloat(iteam[i]);
                }

                //显示选中的建筑块 
                Bitmap pic = setBuildAttr(iteam1_4[0], iteam1_4[1], iteam1_4[2], iteam1_4[3], iteam5_6[0], iteam5_6[1]);
                if (pic != null && toolBoxPos == 0) drawSelect(pic, x, y, iteam1_4[1], iteam1_4[2]);     //编辑区选中块，显示红色边框
            }
        }

        //按偏移量，移动选中的所有建筑块
        private bool moveBuild(int offX, int offY)
        {
            if (PosList.Count == 0) return false;

            for (int i = 0; i < PosList.Count; i++)    //修改选中的建筑块的坐标
                moveBuild(PosList.ElementAt(i), offX, offY);

            drawMap();      //重绘编辑界面
            return true;
        }

        //修改buildPos处的建筑块的位置
        private void moveBuild(BiuildPos buildPos, int offX, int offY)
        {
            int x = buildPos.X, y = buildPos.Y, layer = buildPos.Layer;
            if (layer < 0) return;

            string dataIteam = buildsData[x][y];
            if (buildsData[x][y].Equals("")) return;      //若为空数据则返回     

            string[] iteams = dataIteam.Split('/');       //分割为单独的建筑图块项

            if (layer < iteams.Length)                    //该位置存在图层layer
            {
                if (iteams[layer].Equals("")) return;     //该层无数据
                string[] iteam = iteams[layer].Split('&');//分割数据项

                //修改水平垂直偏移量
                iteam[1] = (F.ToInt(iteam[1]) + offX).ToString();
                iteam[2] = (F.ToInt(iteam[2]) + offY).ToString();

                iteams[layer] = F.ToString(iteam, "&");    //生成建筑块数据项
                buildsData[x][y] = F.ToString(iteams, "/");//修改坐标处的建筑块数据
            }
        }

        

        //根据属性值设置建筑块
        private Bitmap setBuildAttr(int buildIndex, int offX, int offY, int mirror, float rotate, float shrink)
        {
            if (buildIndex == -1) return null;

            //属性值
            textBoxBuildIndex.Text = buildIndex.ToString();
            textBoxOffX.Text = offX.ToString();
            textBoxOffY.Text = offY.ToString();
            comboBoxMirror.SelectedIndex = mirror;
            comboBoxRotate.Text = rotate.ToString();
            textBoxShrink.Text = shrink.ToString();

            //设置属性对应建筑图像
            Bitmap pic = getBuild();              //获取建筑块图像
            
            drawBuild(pic);                       //显示在属性栏中

            return pic;
        }

        private void drawSelect(Bitmap pic, int x, int y, int offX, int offY)
        {
            Rectangle Rect = new Rectangle((int)(Rect2.Left + (y + 0.5) * width - pic.Width / 2) + offX, (int)(Rect2.Top + (x + 0.5) * height - pic.Height / 2) + offY, pic.Width, pic.Height);
            g2.DrawRectangle(new Pen(Color.Red), Rect);
        }

        //获取当前的建筑块属性串
        private string getBuildAttr()
        {
            //绘制一个建筑块的属性设置
            int[] iteamData1_4 = new int[4];
            iteamData1_4[0] = F.ToInt(textBoxBuildIndex.Text.Trim(), -1);//图块编号
            if(iteamData1_4[0] == -1) return "";                        //若未获取到编号，则无属性
            iteamData1_4[1] = F.ToInt(textBoxOffX.Text.Trim());         //图块水平方向偏移量
            iteamData1_4[2] = F.ToInt(textBoxOffY.Text.Trim());         //图块垂直方向偏移量
            iteamData1_4[3] = comboBoxMirror.SelectedIndex;             //镜像

            float[] iteamData5_6 = new float[2];
            iteamData5_6[0] = F.ToFloat(comboBoxRotate.Text.Trim());    //旋转
            iteamData5_6[1] = F.ToFloat(textBoxShrink.Text.Trim(), 1);  //缩放


            //记录建筑块绘制属性值，到建筑块数据数组中
            string str = "";
            for(int i = 0; i < iteamData1_4.Length; i++) str += ((str.Equals("") ? "" : "&") + iteamData1_4[i]);        //项内分割符
            for (int i = 0; i < iteamData5_6.Length; i++) str += ("&" + iteamData5_6[i]);     
            
            return str;
        }

        //获取坐标处对应的建筑块数据
        private int[] getBuildData(int x, int y, int layer)
        {
            int[] iteam = null;
            if (layer < 0) return iteam;

            string dataIteam = buildsData[x][y];
            if (buildsData[x][y].Equals("")) return iteam;  //若为空数据则返回     

            string[] iteams = dataIteam.Split('/');         //分割为单独的建筑图块项
            if (layer < iteams.Length)                      //该位置存在图层layer
            {
                if (iteams[layer].Equals("")) return iteam; //该层无数据
                iteam = F.toIntArray1(iteams[layer], '&');    //获取数据
            }

            return iteam;
        }

        //绘制建筑块图像到属性栏
        private void drawBuild(Bitmap pic)
        {
            gBuild.Clear(pictureBoxbuild.BackColor);

            //显示选中的建筑块
            Point P = new Point((int)((pictureBoxbuild.Width - pic.Width) / 2), (int)((pictureBoxbuild.Height - pic.Height) / 2));
            gBuild.DrawImage(pic, P.X, P.Y, pic.Width, pic.Height);

            //若是当前为使用建筑块状态，则设置为鼠标光标
            if (toolBoxPos == 3) pictureBox2.Cursor = F.GetCursor(pic);
        }
        private void drawBuild(int picIndex)
        {
            gBuild.Clear(pictureBoxbuild.BackColor);

            //显示选中的建筑块
            Image pic = buildTiles[picIndex];            //获取图像
            textBoxBuildIndex.Text = picIndex.ToString();//记录图像编号

            Point P = new Point((int)((pictureBoxbuild.Width - pic.Width) / 2), (int)((pictureBoxbuild.Height - pic.Height) / 2));
            gBuild.DrawImage(pic, P.X, P.Y, pic.Width, pic.Height);
        }

        //更新属性值对应的建筑块图像
        private void updateBuild(object sender, EventArgs e)
        {
            timerDelayDoing(4, 30);
        }
        private void upDataBuild0()
        {
            Bitmap pic = getBuild();                //获取图像
            drawBuild(pic);                         //属性栏显示
        }

        private void timerDrawTool_Tick(object sender, EventArgs e)
        {
            drawTools();
            timerDrawTool.Enabled = false;
        }

        //控制选中的控件位置相对移动
        private void reSite(int x, int y)
        {
            if(moveBuild(x, y)) return;            //移动选中的所有建筑块

            //移动单个选中的建筑块
            int offX = F.ToInt(textBoxOffX.Text.Trim(), 0);
            textBoxOffX.Text = (offX + x).ToString();

            int offY = F.ToInt(textBoxOffY.Text.Trim(), 0);
            textBoxOffY.Text = (offY + y).ToString();

            button1_Click_1(null, null);
        }

        private void 上移ToolStripMenuItem_Click(object sender, EventArgs e)
        { reSite(0, -1);}

        private void 下移ToolStripMenuItem_Click(object sender, EventArgs e)
        { reSite(0, 1); }

        private void 左移ToolStripMenuItem_Click(object sender, EventArgs e)
        { reSite(-1, 0); }

        private void 右移ToolStripMenuItem_Click(object sender, EventArgs e)
        { reSite(1, 0); }

        //导出关卡数据
        private void toolStripExportAll_Click(object sender, EventArgs e)
        {
            for (int i = 0; i < OpendFilesName.Length; i++)
            {
                OutFileProcess(true);       //输出当前编辑的关卡
                JumpFunction(3);            //跳转下一关
            }
            MessageBox.Show("数据已导出");
        }

        private void Form1_KeyUp(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.ControlKey)  //Control键释放
            {
                controlPress = false;
            }
        }

        bool controlPress = false;
        private void Form1_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.KeyCode == Keys.ControlKey)   //Control键按下 
            {
                controlPress = true;
            }
        }

        //显示列选择框
        private void checkSetLines_CheckedChanged(object sender, EventArgs e)
        {
            setCheckLineVisible(checkSetLines.Checked);
        }

        //修改计时炸弹值
        private void buttonStepTime_Click(object sender, EventArgs e)
        {
            if (clickTimeStep.X == -1) return;
            timeStep[clickTimeStep] = F.ToInt(textBoxStepTime.Text, 5); //修改选中的定时炸弹块步数值
            drawPic2(clickTimeStep.X, clickTimeStep.Y);                 //重绘坐标处的图像

            //string str = "";
            //foreach(KeyValuePair<Point, int> iteam in timeStep)
            //    str += iteam.Key.X + "," + iteam.Key.Y + "," + iteam.Value + ";";
            //MessageBox.Show(clickTimeStep.X + "," + clickTimeStep.Y + "定时炸弹块个数：" + timeStep.Count + " (" + str);
        }

        //将定时炸弹块中的数据转化为数组形式，用于数据输出
        private int[][] getTimeStepData()
        {
            if(timeStep.Count == 0)return null;

            int[][] Array = new int[timeStep.Count][];
            for(int i=0; i<timeStep.Count; i++)
            {
                KeyValuePair<Point, int> iteam = timeStep.ElementAt(i);
                Array[i] = new int[] { iteam.Key.X, iteam.Key.Y, iteam.Value};
            }
            return Array;
        }

        //从Array数组载入timeStep值，用于初始载入
        private void setTimeStepData(int[][] Array)
        {
            timeStep.Clear();               //清除原有数据
            foreach (int[] A in Array) if (A.Length == 3) timeStep.Add(new Point(A[0], A[1]), A[2]);
            panelStepTime.Visible = false;  //初始载入设为不可见
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            System.Diagnostics.Process.Start("http://git.oschina.net/scimence/yingjiuchongwu/attach_files");
        }
    }
}
